package org.share.supports.netty.rpc;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.share.develop.common.factoy.NamedThreadFactory;
import org.share.supports.netty.NettyConfig;
import org.share.supports.netty.events.BootstrapHook;
import org.share.supports.netty.rpc.support.AbstractRpcRemoting;

import java.net.InetSocketAddress;


public abstract class AbstractRpcRemotingClient extends AbstractRpcRemoting implements RemotingService, BootstrapHook {



    private final EventLoopGroup eventLoopGroupWorker;
    private final Bootstrap bootstrap = new Bootstrap();
    private final NettyConfig nettyClientConfig;


    public AbstractRpcRemotingClient(){
        this.nettyClientConfig = new NettyConfig();
        int selectorThreadSizeThreadSize = this.nettyClientConfig.getSelectorThreadSizeThreadSize();
        this.eventLoopGroupWorker = new NioEventLoopGroup(selectorThreadSizeThreadSize,
                new NamedThreadFactory(this.nettyClientConfig.getClientSelectorThreadPrefix(), selectorThreadSizeThreadSize));
    }


    public void start() {
        staring();
        this.bootstrap.group(this.eventLoopGroupWorker)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)
                .option(ChannelOption.SO_SNDBUF,153600)
                .option(ChannelOption.SO_RCVBUF, 153600)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) {
                        socketChannelProcess(ch);
                    }
                });
        started();
    }


    public void shutdown() { }



    protected Channel connect(String serverAddress) throws Exception {
        return doConnect(serverAddress);

    }


    private Channel doConnect(String serverAddress) throws Exception {
        Channel channelToServer = null;

        try {
//            RegisterTMRequest
//                    registerTransactionManagerRequest = new RegisterTMRequest(
//                    applicationId, transactionServiceGroup);
//            poolKeyMap.putIfAbsent(serverAddress,
//                    new NettyPoolKey(getTransactionRole(), serverAddress, registerTransactionManagerRequest));
//
//
//            channelToServer = nettyClientKeyPool.borrowObject(poolKeyMap.get(serverAddress));


        } catch (Exception exx) {
            throw new Exception("can not register TM,err:" + exx.getMessage());
        }
        return channelToServer;
    }

    /**
     * Gets new channel.
     *
     * @param address the address
     * @return the new channel
     */
    protected Channel getNewChannel(InetSocketAddress address) {
        Channel channel = null;
        ChannelFuture f = this.bootstrap.connect(address);
//        try {
//            f.await(this.nettyClientConfig.getConnectTimeoutMillis(), TimeUnit.MILLISECONDS);
//            if (f.isCancelled()) {
//                throw new FrameworkException(f.cause(), "connect cancelled, can not connect to services-server.");
//            } else if (!f.isSuccess()) {
//                throw new FrameworkException(f.cause(), "connect failed, can not connect to services-server.");
//            } else {
//                channel = f.channel();
//            }
//        } catch (Exception e) {
//            throw new FrameworkException(e, "can not connect to services-server.");
//        }
        return channel;
    }
}
